aboutsummaryrefslogtreecommitdiff
path: root/src/app/anime/[id]
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/anime/[id]')
-rw-r--r--src/app/anime/[id]/[animeId]/page.jsx56
-rw-r--r--src/app/anime/[id]/[animeId]/video.css30
-rw-r--r--src/app/anime/[id]/info.css83
-rw-r--r--src/app/anime/[id]/loading.css346
-rw-r--r--src/app/anime/[id]/loading.jsx9
-rw-r--r--src/app/anime/[id]/page.jsx50
6 files changed, 574 insertions, 0 deletions
diff --git a/src/app/anime/[id]/[animeId]/page.jsx b/src/app/anime/[id]/[animeId]/page.jsx
new file mode 100644
index 0000000..d59b0a0
--- /dev/null
+++ b/src/app/anime/[id]/[animeId]/page.jsx
@@ -0,0 +1,56 @@
+import { MediaPlayer, MediaProvider } from "@vidstack/react";
+import "@vidstack/react/player/styles/base.css";
+import "@vidstack/react/player/styles/plyr/theme.css";
+import {
+ PlyrLayout,
+ plyrLayoutIcons,
+} from "@vidstack/react/player/layouts/plyr";
+import "./video.css";
+import { redirect } from "next/navigation";
+
+export default async function Video({ params }) {
+ const id = params.animeId;
+
+ // Getting the episode number and the anime name. Kindly ignore!
+ const words = id.split("-");
+ const last_two = words.slice(-2).join(" ");
+ const remainingWords = words.slice(0, -2).join(" ");
+
+ const data = await getVideoLink(id);
+
+ if (data.message) {
+ redirect("/404");
+ }
+
+ const link = data.sources[4].url;
+
+ return (
+ <div>
+ <div className="video2">
+ <p>
+ {last_two} - {remainingWords}
+ </p>
+ <MediaPlayer
+ title={words}
+ src={link}
+ className="testPlayer"
+ playsInline
+ aspectRatio="16/9"
+ load="eager"
+ >
+ <MediaProvider />
+ <PlyrLayout icons={plyrLayoutIcons} />
+ </MediaPlayer>
+ </div>
+ </div>
+ );
+}
+
+async function getVideoLink(id) {
+ const res = await fetch(
+ "https://consumet-api-di2e.onrender.com/anime/gogoanime/watch/" + id,
+ { next: { revalidate: 3600 } } // Video links are revalidated after an hour
+ );
+ const data = res.json();
+ return data;
+}
diff --git a/src/app/anime/[id]/[animeId]/video.css b/src/app/anime/[id]/[animeId]/video.css
new file mode 100644
index 0000000..5ccb58f
--- /dev/null
+++ b/src/app/anime/[id]/[animeId]/video.css
@@ -0,0 +1,30 @@
+.video2 {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 0px auto;
+ width: 50%;
+}
+
+.testPlayer {
+ border-radius: 10px;
+}
+
+.video2 p {
+ color: white;
+ font-family: "Lato";
+ font-size: 20px;
+ text-align: center;
+}
+
+@media (prefers-color-scheme: light) {
+ .video2 p {
+ color: black;
+ }
+}
+
+@media screen and (max-width: 768px) {
+ .video2 {
+ width: 100%;
+ }
+} \ No newline at end of file
diff --git a/src/app/anime/[id]/info.css b/src/app/anime/[id]/info.css
new file mode 100644
index 0000000..2b070d0
--- /dev/null
+++ b/src/app/anime/[id]/info.css
@@ -0,0 +1,83 @@
+.dramaInfoContainer {
+ display: flex;
+ flex-direction: column;
+}
+
+.dramaInfo {
+ display: flex;
+ flex-direction: column;
+ width: 95%;
+ margin: 0px auto;
+}
+
+.titleContainer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.titleContainer p {
+ color: var(--neon-green);
+ width: 60%;
+ font-family: "Kanit";
+ font-size: 24px;
+}
+
+.titleContainer img {
+ border-radius: 10px;
+}
+
+.animeDescription {
+ color: #ffffff81;
+ font-family: "Lato";
+ font-size: 16px;
+ max-height: 120px;
+ margin: 20px auto;
+ text-align: center;
+ overflow-y: auto;
+}
+
+.buttonContainer {
+ margin: 5px auto;
+ text-align: center;
+ max-height: 200px;
+ overflow-y: auto;
+}
+
+.dramaButton {
+ padding: 8px;
+ font-family: "Atkinson Hyperlegible";
+ font-size: 18px;
+ margin: 5px;
+ width: 50px;
+ border-radius: 5px;
+ border: none;
+ background-color: var(--light-green);
+ cursor: pointer;
+}
+
+.dramaButton:hover {
+ background-color: var(--soft-purple);
+}
+
+.infoPageContainer {
+ display: flex;
+ height: 100dvh;
+ justify-content: center;
+ align-items: center;
+}
+
+.infoPageContainer p {
+ color: white;
+}
+
+@media (prefers-color-scheme: light) {
+ .animeDescription {
+ color: black;
+ }
+
+ .infoPageContainer p {
+ color: black;
+ }
+
+} \ No newline at end of file
diff --git a/src/app/anime/[id]/loading.css b/src/app/anime/[id]/loading.css
new file mode 100644
index 0000000..aa3a519
--- /dev/null
+++ b/src/app/anime/[id]/loading.css
@@ -0,0 +1,346 @@
+.loadingContainer {
+ color: white;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 80dvh;
+}
+
+
+.text-flicker-in-glow {
+ -webkit-animation: text-flicker-in-glow 4s linear both;
+ animation: text-flicker-in-glow 4s linear both;
+ font-size: 36px;
+ font-family: "Kanit";
+}
+
+/* ----------------------------------------------
+ * Generated by Animista on 2024-3-21 9:58:16
+ * Licensed under FreeBSD License.
+ * See http://animista.net/license for more info.
+ * w: http://animista.net, t: @cssanimista
+ * ---------------------------------------------- */
+
+/**
+ * ----------------------------------------
+ * animation text-flicker-in-glow
+ * ----------------------------------------
+ */
+
+@-webkit-keyframes text-flicker-in-glow {
+ 0% {
+ opacity: 0;
+ }
+
+ 10% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 10.1% {
+ opacity: 1;
+ text-shadow: none;
+ }
+
+ 10.2% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.25);
+ }
+
+ 20.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.5% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 50% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 100% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+}
+
+@keyframes text-flicker-in-glow {
+ 0% {
+ opacity: 0;
+ }
+
+ 10% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 10.1% {
+ opacity: 1;
+ text-shadow: none;
+ }
+
+ 10.2% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 20.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.25);
+ }
+
+ 20.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 30.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.5% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 30.6% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 45.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 50% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.45), 0 0 60px rgba(255, 255, 255, 0.25);
+ }
+
+ 55.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 57.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35);
+ }
+
+ 60.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 65.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.35), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 75.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 77.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.55), 0 0 60px rgba(255, 255, 255, 0.4), 0 0 110px rgba(255, 255, 255, 0.2), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 85.1% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86% {
+ opacity: 0;
+ text-shadow: none;
+ }
+
+ 86.1% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+
+ 100% {
+ opacity: 1;
+ text-shadow: 0 0 30px rgba(255, 255, 255, 0.6), 0 0 60px rgba(255, 255, 255, 0.45), 0 0 110px rgba(255, 255, 255, 0.25), 0 0 100px rgba(255, 255, 255, 0.1);
+ }
+}
+
+@media (prefers-color-scheme: light) {
+ .loadingContainer {
+ color: black;
+ }
+} \ No newline at end of file
diff --git a/src/app/anime/[id]/loading.jsx b/src/app/anime/[id]/loading.jsx
new file mode 100644
index 0000000..dfa397c
--- /dev/null
+++ b/src/app/anime/[id]/loading.jsx
@@ -0,0 +1,9 @@
+import "./loading.css";
+
+export default function Loading() {
+ return (
+ <div className="loadingContainer">
+ <p className="text-flicker-in-glow">Loading</p>
+ </div>
+ );
+}
diff --git a/src/app/anime/[id]/page.jsx b/src/app/anime/[id]/page.jsx
new file mode 100644
index 0000000..3e2b1f0
--- /dev/null
+++ b/src/app/anime/[id]/page.jsx
@@ -0,0 +1,50 @@
+import "./info.css";
+import Image from "next/image";
+import Link from "next/link";
+
+export default async function AnimeInfo({ params }) {
+ let animeID = params.id;
+
+ const info = await getAnimeInfo(animeID);
+
+ return (
+ <div className="dramaInfoContainer">
+ <div className="dramaInfo">
+ {info && (
+ <div>
+ <div className="titleContainer">
+ <p>{info.title}</p>
+ <Image
+ src={info.image}
+ width={140}
+ height={190}
+ alt="Drama"
+ />
+ </div>
+ <p className="animeDescription">{info.description}</p>
+ </div>
+ )}
+
+ <div className="buttonContainer">
+ {info &&
+ info.episodes.map((item, index) => (
+ <Link href={`/anime/watch/${item.id}`} key={index}>
+ <button className="dramaButton">
+ {item.number}
+ </button>
+ </Link>
+ ))}
+ </div>
+ </div>
+ </div>
+ );
+}
+
+async function getAnimeInfo(anime_id) {
+ const res = await fetch(
+ "https://anime-sensei-api.vercel.app/anime/gogoanime/info/" + anime_id,
+ { next: { revalidate: 1800 } }
+ );
+ const data = res.json();
+ return data;
+}